#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "Main.h"
#include "login.pb.h"
#include "CheckTemplate.h"

#pragma pack(1)
struct PackageHead
{
    uint16_t size;//包括PackageHead的数据包总长
    uint16_t main;
    uint16_t sub;
};

#pragma pack() 
const uint32_t BUF_SIZE_RECV_ALL =1024*1024;//一个数据包总长（包括头4字节的长度）
const uint32_t BUF_SIZE_RECV_DATA =BUF_SIZE_RECV_ALL-sizeof(PackageHead);//一个数据包总长（不包括头4字节的长度）

class Client;
std::map<int,Client*> g_mapInMap;

void broadCast(const uint16_t main,const uint16_t sub,google::protobuf::Message &move,int fdExlude=0);
class Client
{
public:

    // char bufRecv[BUF_SIZE_RECV];
    std::vector<char> bufRecv_;//以后改成无锁循环缓冲区
    bool onRecv(char (&buf)[RECV_BUF_LEN_ONCE], uint32_t size)
    {
        IF_NOT( bufRecv_.size()+size <= BUF_SIZE_RECV_ALL )
        {
            BEGIN_LOG_OBJ_DEBUG << "数据包太大，应该断线," << size << END_LOG_OBJ;
            return false;
        }
        bufRecv_.insert(bufRecv_.end(),&(buf[0]),&(buf[size]));
        while(read1Package())
        {
        }
        return true;
    }
    bool read1Package()
    {
        if(sizeof(PackageHead) > bufRecv_.size() )
            return false;

        auto *pPackageHead = (const PackageHead*)&(bufRecv_[0]);
        if( pPackageHead->size > bufRecv_.size())
        {
            BEGIN_LOG_OBJ_DEBUG << pPackageHead->size << "=pPackageHead->size,数据包还没收完，继续收," << fd_ << ",bufRecv_.size="<< bufRecv_.size() << END_LOG_OBJ;
            return false;
        }
        onRecv1PackageOk(pPackageHead->main,pPackageHead->sub,&(bufRecv_[sizeof(PackageHead)]),pPackageHead->size-sizeof(PackageHead));
        bufRecv_.erase(bufRecv_.begin(),bufRecv_.begin()+pPackageHead->size);
        return true;
    }
    virtual void onRecv1PackageOk(const uint16_t main ,const uint16_t sub,const char *buf,const uint32_t size)
    {
        switch (main)
        {
        case 1:
            switch (sub)
            {
            case 1:
            {
                testSvr::Login login;
                const auto ok = login.ParseFromArray(buf,size);
                printf("ParseFromArray,ok=%d,size=%d\n",ok,size);
                IF_OK( ok )
                {
                    // printf("login,name=%s",login.name().c_str());
                    login.set_server_fd(fd_);
                    // char bufSend[128]={0};
                    // login.SerializeToArray(bufSend,sizeof(bufSend));
                    // const auto ret = write( fd_,bufSend,login.ByteSizeLong() );
                    // printf("login,send,ret=%d\n",ret);
                    send1Package(1,1,login);
                    g_mapInMap[fd_]=this;
                    testSvr::EnterScene es;
                    es.set_name( login.name() );
                    es.set_server_fd( fd_ );
                    *es.mutable_pos()=pos_;
                    broadCast(1,2,es);
                }
                break;
            }
            default:
                break;
            }
            break;
        case 2:
        switch (sub)
        {
        case 1:
            {
                testSvr::Move move;
                const auto ok = move.ParseFromArray(buf,size);
                printf("ParseFromArray,ok=%d,size=%d\n",ok,size);
                move.set_server_fd(fd_);
                broadCast(main,sub,move);
                pos_ = move.pos();
            }
            break;
        
        default:
            break;
        }
        default:
            break;
        }
    }
    void send1Package( uint16_t main,uint16_t sub , google::protobuf::Message &msg )
    {
        std::vector<uint8_t> vecByte;
        PackageHead head;
        head.size = msg.ByteSize()+sizeof(PackageHead);
        head.main = main;
        head.sub = sub;
        vecByte.insert(vecByte.end(),(const uint8_t*)&head,(const uint8_t*)&head+sizeof(head));//重复代码，要合并
        uint8_t bufSend[128]={0};
        const auto ok = msg.SerializeToArray(bufSend,sizeof(bufSend));
        CHECK(ok);
        vecByte.insert(vecByte.end(),(const uint8_t*)bufSend,(const uint8_t*)bufSend+msg.ByteSize() );//重复代码，要合并
        const auto ret = write( fd_,&(vecByte[0]),head.size );
        printf("send1Package,send,ret=%d,ok=%d\n",ret,ok);
    }
    void onClose(const int fd)
    {
        VERIFY_LOG( FoundMap(g_mapInMap,fd_));
        g_mapInMap.erase(fd_);
        VERIFY_LOG(fd_==fd);
        fd_ = 0;
        bufRecv_.clear();

    }
    void onAccept(const int fd)
    {
        printf("onAccept:%d\n",fd);
        VERIFY_LOG(fd_==0);
        fd_ = fd;
    }
    int fd_=0;
    testSvr::Position pos_;
};
void broadCast(const uint16_t main,const uint16_t sub,google::protobuf::Message &move,int fdExlude)
{
    for( auto &refKv : g_mapInMap)
    {
        if(refKv.second->fd_ == fdExlude )
            return;

        refKv.second->send1Package(main,sub,move);
    }
}
std::map<int,Client> g_mapClient;
void onRecv( const int fd , char (&buf)[RECV_BUF_LEN_ONCE], int size)
{
    BEGIN_LOG_OBJ_DEBUG << size << END_LOG_OBJ;
	// printf("onRecv:%s\n",buf);
    // //数据包一个ushort长度，后面缓存是protobuf
    // testSvr::Login login;
    // const auto ok = login.ParseFromArray(buf,size);
    // printf("ParseFromArray,ok=%d,size=%d\n",ok,size);
    // if( ok )
    // {
    //     printf("login,name=%s",login.name().c_str());
    //     login.set_server_fd(fd);
    //     char bufSend[128]={0};
    //     login.SerializeToArray(bufSend,sizeof(bufSend));
    //     const auto ret = write( fd,bufSend,login.ByteSizeLong() );
    //     printf("login,send,ret=%d\n",ret);
    // }
    g_mapClient[fd].onRecv(buf,size);
}

void onAccept( int fd )
{
    g_mapClient[fd].onAccept(fd);
}

void onClose( const int fd )
{
    printf("断开连接onClose:%d\n",fd);
    g_mapClient[fd].onClose(fd);
}